import json
import re

from meiduo_mall.settings import VERIFY_EMAIL_URL
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.views import View
from apps.users.models import User, Address
from utils.logger import logger
from django.contrib.auth import login, authenticate, logout
from utils.views import LoginRequiredJsonMixin
from utils.endecrypt import encrypt_dict, decrypt_dict
# Create your views here.
"""
注册功能:
    1. 用户名，检测是否重复
    2. 手机号是否重复
    3. 后端验证码.
    4. 手机验证码验证.
    5. 注册功能
"""


class UsernameCountView(View):
    """
    检查用户名是否重复
    """
    def get(self, request, uname):
        """
        1. 接受用户名.
        2. 根据用户名查询数据库
        3. 返回响应.
        """
        # 1. 接受用户名. 进行校验字段
        # if not re.match('[a-zA-Z0-9_-]{5,20}', username):
        #    return JsonResponse({'code': 200, 'errmsg': '用户名不满足需求'})

        # 2. 根据用户名查询数据库
        count = User.objects.filter(username=uname).count()
        logger.info(f'check username: {uname} count:{count}')
        # 3. 返回响应.
        return JsonResponse({'code': 0, 'count': count, 'errmsg': 'ok'})


class MobileCountView(View):
    """
    检查手机号是否重复
    """
    def get(self, request, mid):
        # 1. 手机号校验, 通过转换器进行校验了.
        print("call MobileCountView.get")
        # 2. 根据手机号查询数据库.
        count = User.objects.filter(mobile=mid).count()
        logger.info(f'check mobile: {mid} count:{count}')
        # 3. 返回响应
        return JsonResponse({'code': 0, 'count': count, 'errmsg': 'ok'})


class RegisterView(View):
    """
    注册账号
    """
    def post(self, request):
        # 1. 接受请求数据(post--json)
        body_bytes = request.body
        body_str = body_bytes.decode()
        body_dict = json.loads(body_str)

        # 2. 获取数据.
        username = body_dict.get('username')
        password = body_dict.get('password')
        password2 = body_dict.get('password2')
        mobile = body_dict.get('mobile')
        allow = body_dict.get('allow')

        # 3. 验证数据.
        if not all([username, password, password2, mobile, allow]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'}, json_dumps_params={'ensure_ascii': False})
        # 用户名判断
        if not re.match(r'[a-zA-Z0-9_-]{5,20}', username):
            return JsonResponse({'code': 400, 'errmsg': '用户名不合规则'}, json_dumps_params={'ensure_ascii': False})
        if password != password2:
            return JsonResponse({'code': 400, 'errmsg': '两次密码不一致'}, json_dumps_params={'ensure_ascii': False})
        if len(password) < 6:
            return JsonResponse({'code': 400, 'errmsg': '密码长度小于6位'}, json_dumps_params={'ensure_ascii': False})
        if not re.match(r'1[3-57-9]\d{9}', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号不合法'}, json_dumps_params={'ensure_ascii': False})
        if int(allow)==0:
            return JsonResponse({'code': 400, 'errmsg': '未同意协议条款'}, json_dumps_params={'ensure_ascii': False})

        # 检查用户名是否重复
        user_count = User.objects.filter(username=username).count()
        if user_count > 0:
            return JsonResponse({'code': 400, 'errmsg': '用户名已被注册'}, json_dumps_params={'ensure_ascii': False})

        # 检查手机号是否重复
        mobile_count = User.objects.filter(mobile=mobile).count()
        if mobile_count > 0:
            return JsonResponse({'code': 400, 'errmsg': '手机号已被注册'}, json_dumps_params={'ensure_ascii': False})

        # 4. 数据入库.
        # User.objects.create(username=username, password=password, mobile=mobile)
        # 这种入库，没有进行密码加密.
        # 通过User内部的创建create_user, 来实现.
        user = User.objects.create_user(username=username, password=password, mobile=mobile)
        # 接口内部已经进行保存了.
        # user.save()

        login(request, user)
        # 利用系统django进行登陆进行状态保持.

        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username)
        return response


"""
需求1: 注册成功后，自动登陆.
需求2: 注册成功后，手动登陆.
"""


"""
登陆:
    前端:
        当用户把用户名，密码输入后，发送登陆请求到服务端.
        url. /login/   post请求, {username, password, remembered}
    后端:
        请求:
        业务逻辑
        响应: json, 0 成功， 400, 失败.
步骤：
    1. 接受数据.
    2. 验证数据.
    3. 验证用户名和密码是否正确.
    4. 保存session
    5. 判断是否记住登陆.
    6. 返回响应
        
"""


class LoginView(View):
    def post(self, request):
        # 1. 接受数据.
        data = json.loads(request.body.decode())
        username = data.get('username')
        password = data.get('password')
        remembered = data.get('remembered')

        # 2. 验证数据.
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'}, json_dumps_params={'ensure_ascii': False})

        # 如果是手机号，则用手机号登陆，否则用账户名登陆
        if re.match('1[3-9]\d{9}', username):
            User.USERNAME_FIELD = 'mobile'
        else:
            User.USERNAME_FIELD = 'username'

        # 3. 验证密码.
        # 使用系统的登陆函数，可以不用对密码进行加密判断。内部已经做了加密处理.
        user = authenticate(username=username, password=password)
        if user is None:
            return JsonResponse({'code': 400, 'errmsg': '账号或密码错误'}, json_dumps_params={'ensure_ascii': False})

        # 4. session.
        login(request, user)

        # 5. 记住登陆.
        if remembered:
            # 记住登陆. 默认2周.
            request.session.set_expiry(None)
        else:
            # 不记住登陆.
            request.session.set_expiry(0)

        # 设置Cookie, 让客户端显示用户名称.
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username)
        # 返回响应.
        return response


class LogoutView(View):
    def delete(self, request):
        logout(request)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.delete_cookie('username')
        return response


class CenterView(LoginRequiredJsonMixin, View):
    """
    使用 LoginRequireMixin,  未登录的用户，会重定向，但是不是json数据，和前后端分离冲突.
    """
    def get(self, request):
        # request.user 是已经登录的用户了.
        info_data = {
            'username':request.user.username,
            'mobile':request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active
        }
        return JsonResponse({'code':0, 'errmsg':'ok', 'info_data': info_data})


"""
需求: 保存邮箱.
     发送一封激活邮件.
     用户激活邮件.
邮箱验证逻辑.
    用户输入邮箱， 点击保存， 发送 axios.
    更新数据， put请求.
    # 1. 接受请求
    # 2. 获取数据
    # 3. 保存邮箱地址
    # 4. 发送一封激活邮件
    # 5. 返回响应

    
"""

"""
发送邮件:
1. 设置163服务器，开启授权码

"""


class EmailView(View):
    """添加邮箱"""
    def put(self, request):
        # 1. 接受请求
        json_data = json.loads(request.body.decode())
        # 2. 获取数据
        email = json_data.get('email')
        if email is None:
            return JsonResponse({'code': 400, 'errmsg': '无效邮箱'}, json_dumps_params={'ensure_ascii': False})
        # 验证邮箱.
        # 3. 保存邮箱地址
        user = request.user
        user.email = email
        user.save()
        # 4. 发送一封激活邮件
        # 发送邮件.
        self.send_verify_email(request, email)
        # 5. 返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})

    def send_verify_email(self, request, mail):

        subject = '美多商城激活邮件'
        token = encrypt_dict({'user_id': request.user.id})
        html_message = f'请点击以下链接进行激活<br>  <a href="{VERIFY_EMAIL_URL}?token={token}">激活</a>'
        from_email = '美多商城<zhush_2005@163.com>'
        recipient_list = ['42907610@qq.com', mail]
        from celery_tasks.send_email.tasks import celery_send_email
        celery_send_email.delay(subject=subject, message="",  html_message=html_message, from_email=from_email,
                                recipient_list=recipient_list)


class EmailVerifyView(View):
    def put(self, request):
        # 接受请求
        token = request.GET.get('token')
        if token is None:
            return JsonResponse({'code': 400, 'errmsg': '验证失败'}, json_dumps_params={'ensure_ascii': False})
        data = decrypt_dict(token)
        if data is None:
            return JsonResponse({'code': 400, 'errmsg': '验证失败'}, json_dumps_params={'ensure_ascii': False})
        user_id = data.get('user_id')
        user_obj = User.objects.get(id=user_id)
        if user_obj is None:
            return JsonResponse({'code': 400, 'errmsg': '无效的用户id'}, json_dumps_params={'ensure_ascii': False})
        user_obj.email_active = True
        user_obj.save()
        return JsonResponse({'code': 0, 'errmsg': '验证完成'}, json_dumps_params={'ensure_ascii': False})


class AddressCreateView(LoginRequiredJsonMixin, View):
    """
    收货地址创建
    """
    def post(self, request):
        # 获取参数
        data = json.loads(request.body.decode())

        # 解析参数
        receiver = data.get('receiver')
        province_id = data.get('province_id')
        city_id = data.get('city_id')
        district_id = data.get('district_id')
        place = data.get('place')
        mobile = data.get('mobile')
        tel = data.get('tel')
        email = data.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, 'errmsg': '信息不全'}, json_dumps_params={'ensure_ascii': False})

        # 创建地址
        address = Address.objects.create(
            user_id=request.user.id,
            title=receiver,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email,
            is_delete=False,
        )

        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province_id': address.province_id,
            'city_id': address.city_id,
            'district_id': address.district_id,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email,
        }

        if request.user.default_address_id is None:
            request.user.default_address_id = address.id
            request.user.save()

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'address': address_dict})


class AddressView(LoginRequiredJsonMixin, View):
    """
    收货地址查询
    """
    def get(self, request):
        user_id = request.user.id
        addresses = Address.objects.filter(user_id=user_id, is_delete=False)
        addresses_list = []
        for address in addresses:
            addresses_list.append({
                'id': address.id,
                'title': address.title,
                'receiver': address.receiver,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'province_id': address.province_id,
                'city_id': address.city_id,
                'district_id': address.district_id,
                'place': address.place,
                'mobile': address.mobile,
                'tel': address.tel,
                'email': address.email,
            })
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'addresses': addresses_list,
                             'default_address_id': request.user.default_address_id})


class AddressSetDefaultView(LoginRequiredJsonMixin, View):
    """
    设置默认地址的逻辑;
    """
    def put(self, request, id):
        # addresses = request.user.addresses
        # id_valid = False
        # for address in addresses:
        #     if address.id == id:
        #         id_valid = True
        #         break

        address = Address.objects.get(id=id, is_delete=False)
        id_valid = address is not None and address.user_id == request.user.id

        if not id_valid:
            return JsonResponse({'code': 400, 'errmsg': 'id不合法'}, json_dumps_params={'ensure_ascii': False})

        request.user.default_address_id = id
        request.user.save()

        return JsonResponse({'code': 0, 'errmsg': 'ok', }, json_dumps_params={'ensure_ascii': False})


class AddressChangeAliasView(LoginRequiredJsonMixin, View):
    def put(self, request, id):
        body_dict = json.loads(request.body.decode())
        new_title = body_dict.get('title')
        address = Address.objects.get(id=id, is_delete=False)
        id_valid = address is not None and address.user_id == request.user.id
        if not id_valid:
            return JsonResponse({'code': 400, 'errmsg': 'id不合法'}, json_dumps_params={'ensure_ascii': False})
        address.title = new_title
        address.save()
        return JsonResponse({'code': 0, 'errmsg': 'ok', }, json_dumps_params={'ensure_ascii': False})


class AddressDetailView(LoginRequiredJsonMixin, View):
    """
    修改地址
    """
    def put(self, request, id):

        body_dict = json.loads(request.body.decode())
        address = Address.objects.get(id=id, is_delete=False)
        id_valid = address is not None and address.user_id == request.user.id
        if not id_valid:
            return JsonResponse({'code': 400, 'errmsg': 'id不合法'}, json_dumps_params={'ensure_ascii': False})

        receiver = body_dict.get('receiver')
        province_id = body_dict.get('province_id')
        city_id = body_dict.get('city_id')
        district_id = body_dict.get('district_id')
        place = body_dict.get('place')
        mobile = body_dict.get('mobile')
        tel = body_dict.get('tel')
        email = body_dict.get('email')
        address.receiver = receiver
        address.province_id = province_id
        address.city_id = city_id
        address.district_id = district_id
        address.place = place
        address.mobile = mobile
        address.tel = tel
        address.email = email
        address.save()

        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province_id': address.province_id,
            'city_id': address.city_id,
            'district_id': address.district_id,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email,
        }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'address': address_dict},
                            json_dumps_params={'ensure_ascii': False})

    def delete(self, request, id):
        address = Address.objects.get(id=id, is_delete=False)
        id_valid = address is not None and address.user_id == request.user.id
        if not id_valid:
            return JsonResponse({'code': 400, 'errmsg': 'id不合法'}, json_dumps_params={'ensure_ascii': False})

        # 假删除.
        address.is_delete = True
        address.save()
        if request.user.default_address_id == id:
            request.user.default_address_id = 0
            request.user.save()
        return JsonResponse({'code': 0, 'errmsg': 'ok'},
                            json_dumps_params={'ensure_ascii': False})


